#include "config.h"
#include "network.h"
#include "student.h"
#include "file.h"      
#include "log.h"        
#include <pthread.h>
#include <stdlib.h>
#include <string.h>

// 全局链表和互斥锁（在student.c中定义，此处声明）
extern Student *g_student_list;
extern pthread_mutex_t g_list_mutex;

int current_connections = 0;    //当前连接数计数器
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;    //保护计数器的锁

typedef struct {
    int client_fd;     // 客户端套接字
    ServerConfig config; // 服务器配置（在 config.h 中定义）
} ClientArg;

//拼接字符串，用于组成响应
void str_cat(char *dest, const char *src) {
    strcat(dest, src);
    strcat(dest, "\n");  // 换行分隔
}

//解析并执行客户端命令
void execute_command(const char *command, char *response, ServerConfig *config) {
    char cmd_copy[1024];
    strcpy(cmd_copy, command);  // 复制命令，避免修改原字符串

    // 分割命令（第一个单词为操作类型：ADD/DELETE等）
    char *op = strtok(cmd_copy, " ");
    if (op == NULL) {
        strcpy(response, "错误：命令为空");
        return;
    }

    // 1. 处理ADD命令（格式：ADD 学号 姓名 性别 年龄）
    if (strcmp(op, "ADD") == 0) {
        char *id = strtok(NULL, " ");
        char *name = strtok(NULL, " ");
        char *gender = strtok(NULL, " ");
        char *age_str = strtok(NULL, " ");

        // 检查参数是否完整
        if (id == NULL || name == NULL || gender == NULL || age_str == NULL) {
            strcpy(response, "错误：ADD命令参数不足（格式：ADD 学号 姓名 性别 年龄）");
            return;
        }
        int age = atoi(age_str);  // 年龄转整数

        // 生成序号（链表长度+1）
        int num = get_list_length() + 1;

        // 插入链表
        int ret = add_student(num, id, name, gender, age);
        if (ret == 0) {
            sprintf(response, "添加学生成功\n添加学生信息：学号：%s，姓名：%s，性别：%s，年龄：%d", id, name, gender, age);
            // 记录日志（操作类型，操作内容，结果）
            log_write(config->log_file, "INFO", response);
        } else {
            strcpy(response, "添加失败，请检查学生信息是否填写正确");
            log_write(config->log_file, "ERROR", response);
        }
        return;
    }

    // 2. 处理DELETE命令（格式：DELETE 学号）
    if (strcmp(op, "DELETE") == 0) {
        char *id = strtok(NULL, " ");
        if (id == NULL) {
            strcpy(response, "错误：DELETE命令参数不足（格式：DELETE 学号）");
            return;
        }

        int ret = delete_student(id);
        if (ret == 0) {
            sprintf(response, "删除成功");
            log_write(config->log_file, "INFO", response);
        } else {
            sprintf(response, "删除失败（可能原因：该学生信息不存在 或学号不正确）");
            log_write(config->log_file, "ERROR", response);
        }
        return;
    }

    // 3. 处理UPDATE命令（格式：UPDATE 旧学号 新学号 新姓名 新性别 新年龄）
    if (strcmp(op, "UPDATE") == 0) {
        char *old_id = strtok(NULL, " ");
        char *new_id = strtok(NULL, " ");
        char *new_name = strtok(NULL, " ");
        char *new_gender = strtok(NULL, " ");
        char *new_age_str = strtok(NULL, " ");

        if (old_id == NULL || new_id == NULL || new_name == NULL || new_gender == NULL || new_age_str == NULL) {
            strcpy(response, "错误：UPDATE参数不足（格式：UPDATE 旧学号 新学号 新姓名 新性别 新年龄）");
            return;
        }
        int new_age = atoi(new_age_str);

        int ret = update_student(old_id, new_id, new_name, new_gender, new_age);
        if (ret == 0) {
            sprintf(response, "更新成功\n更新后学生信息：学号：%s，姓名：%s，性别：%s，年龄：%d",new_id, new_name, new_gender, new_age);
            log_write(config->log_file, "INFO", response);
        } else {
            sprintf(response, "更新失败（可能原因：该学生信息不存在 或 新学号已存在）");
            log_write(config->log_file, "ERROR", response);
        }
        return;
    }

    // 4. 处理SEARCH命令（格式：SEARCH 关键字）
    if (strcmp(op, "SEARCH") == 0) {
        char *keyword = strtok(NULL, " ");
        if (keyword == NULL) {
            strcpy(response, "错误：SEARCH参数不足（格式：SEARCH 关键字）");
            return;
        }

        Student *result = NULL;
        int count = search_student(keyword, &result);

        if (count == 0) {
            strcpy(response, "查询结果：无匹配学生");
        } else {
            sprintf(response, "查询结果（共%d条）：", count);
            sprintf(response, "\n序号\t学号\t姓名\t性别\t年龄\n");
            Student *temp = result;
            while (temp != NULL) {  // 拼接所有匹配结果
                char line[200];
                sprintf(line, "%d\t%s\t%s\t%s\t%d\n",
                        temp->num, temp->id, temp->name, temp->gender, temp->age);
                str_cat(response, line);
                temp = temp->next;
            }
        }
        //释放结果链表内存
        Student *current = result;
        while (current != NULL) {
            Student *next = current->next;
            free(current);  // 释放当前节点
            current = next;
        }
        
        log_write(config->log_file, "INFO", "执行SEARCH命令");
        return;
    }

    // 5. 处理SAVE命令（格式：SAVE）
    if (strcmp(op, "SAVE") == 0) {
        int ret = save_to_file(config);
        if (ret == 0) {
            strcpy(response, "成功：数据已保存到文件");
            log_write(config->log_file, "INFO", response);
        } else {
            strcpy(response, "失败：保存文件失败");
            log_write(config->log_file, "ERROR", response);
        }
        return;
    }

    // 未知命令
    sprintf(response, "错误：未知命令（请输入正确命令：ADD/DELETE/UPDATE/SEARCH/SAVE/EXIT）");
}

//处理客户端请求
void *handle_client(void *arg) {
    // 解析参数（客户端fd和服务器配置）
    ClientArg *client_arg = (ClientArg*)arg;
    int client_fd = client_arg->client_fd;
    ServerConfig config = client_arg->config;
    free(client_arg);  // 释放内存

    char buffer[1024] = {0};
    char response[2048] = {0};  // 响应缓冲区（可以容纳多条查询结果）

    // 循环处理客户端命令（直到客户端发送EXIT）
    while (1) {
        ssize_t recv_len = recv_data(client_fd, buffer, sizeof(buffer));
        if (recv_len <= 0) {
            break;  // 连接断开或错误
        }

        // 处理EXIT命令
        if (strcmp(buffer, "EXIT") == 0) {
            strcpy(response, "客户端已退出");
            send_data(client_fd, response);
            log_write(config.log_file, "INFO", "客户端正常退出");
            break;
        }

        // 解析并执行命令
        execute_command(buffer, response, &config);
        // 发送响应给客户端
        send_data(client_fd, response);
        // 清空缓冲区
        memset(buffer, 0, sizeof(buffer));
        memset(response, 0, sizeof(response));
    }

    close(client_fd);

    // 连接关闭时，减少当前连接数
    pthread_mutex_lock(&count_mutex);
    current_connections--;
    pthread_mutex_unlock(&count_mutex);

    log_write(config.log_file, "INFO", "客户端连接已关闭");
    return NULL;
}

//
int main() {
    // 1. 加载配置
    const char *config_path = "conf/server.conf";
    ServerConfig config;
    if (load_server_config(config_path, &config) != 0) {
        fprintf(stderr, "错误：加载配置失败: %s\n", config_path);
        return 1;
    }

    // 2. 初始化日志（创建日志文件）
    init_log(config.log_file);

    // 3. 从文件加载学生数据
    load_from_file(&config);

    // 4. 初始化网络
    int listen_fd = init_server_socket(&config);
    if (listen_fd == -1) {
        log_write(config.log_file, "ERROR", "初始化网络失败");
        return 1;
    }
    log_write(config.log_file, "INFO", "服务器启动成功");

    // 5. 循环接受客户端连接
    while (1) {
        struct sockaddr_in client_addr;
        int client_fd = accept_client(listen_fd, &client_addr);
        if (client_fd == -1) {
            log_write(config.log_file, "ERROR", "接受客户端连接失败");
            continue;
        }

        // 检查连接数是否超限
        pthread_mutex_lock(&count_mutex);
        if (current_connections >= config.max_connections) {
            pthread_mutex_unlock(&count_mutex);
            close(client_fd);   // 超过限制，立即关闭当前连接
            log_write(config.log_file, "ERROR", "拒绝连接：已达到客户端最大连接数");
            continue;
        }
        current_connections++;      //增加当前连接数
        pthread_mutex_unlock(&count_mutex);

        // 发送连接成功消息
        send_data(client_fd, "连接成功");
        log_write(config.log_file, "INFO", "客户端连接成功");

        // 准备线程参数（包含客户端fd和配置）
        ClientArg *arg = (ClientArg*)malloc(sizeof(ClientArg));
        arg->client_fd = client_fd;
        arg->config = config;  // 复制配置
       
        // 创建线程
        pthread_t tid;
        if (pthread_create(&tid, NULL, handle_client, arg) != 0) {
            perror("创建线程失败");
            close(client_fd);
            free(arg);

            //线程创建失败时，减少客户端连接数
            pthread_mutex_lock(&count_mutex);
            current_connections--;
            pthread_mutex_unlock(&count_mutex);

            log_write(config.log_file, "ERROR", "创建线程失败");
            continue;
        }
        pthread_detach(tid);
        log_write(config.log_file, "INFO", "新客户端连接，已创建线程处理");
    }

    close(listen_fd);
    destroy_student_list();
    return 0;
}